using System;
using System.Collections.Generic;
using CLELCore.Assembly.CLELInstructions;
using CLELCore.Assembly.Descriptors.ClassDescriptors;

namespace opt.Analysis.Set
{
	public class GenKill
	{
		private List<BitSet> gen;
		private List<BitSet> kill;
		private List<BitSet> local_stores;

		public List<BitSet> Gen
		{
			get
			{
				return gen;
			}
		}

		public List<BitSet> Kill
		{
			get
			{
				return kill;
			}
		}

		public List<BitSet> Stores
		{
			get
			{
				return local_stores;
			}
		}

		public GenKill(List<CLELInstruction> code,List<ClassDescriptor> locals)
		{
			if(code == null)
				throw new ArgumentException("Code cannot be null");
			
			//which locals to consider for GenKill
			BitSet use_locals = new BitSet();
			//set of which instructions store which local
			local_stores = new List<BitSet>();
			int code_count = code.Count;

			int i,j,temp,stop;
			if(locals != null && locals.Count > 0)
			{
				stop = locals.Count;
				for(i = 0;i < stop;i++)
				{
					use_locals.Set(i);
					
					local_stores.Add(new BitSet());
				}

				for(i = 0;i < code_count;i++)
				{
					temp = -1;
					//if a pointer is gotten from it, remove it
					if(LoadStoreUtilities.GetLoadLocalAddressNum(code[i],ref temp))
					{
						use_locals.Unset(temp);
					}

					temp = -1;
					if(LoadStoreUtilities.GetStoreLocalNum(code[i],ref temp))
					{
						local_stores[temp].Set(i);
					}
				}
			}

			gen = new List<BitSet>();
			kill = new List<BitSet>();

			BitSet g;
			BitSet k;
			BitSet local_stores_temp;
			List<Int32> local_stores_num;
			for(i = 0;i < code_count;i++)
			{
				g = new BitSet();
				k = new BitSet();

				temp = -1;
				if(LoadStoreUtilities.GetStoreLocalNum(code[i],ref temp))
				{
					if(use_locals.IsSet(temp))
					{
						g.Set(i);
						
						local_stores_temp = local_stores[temp];
						local_stores_num = local_stores_temp.GetNumberSet();
						stop = local_stores_num.Count;
						for(j = 0;j < stop;j++)
						{
							temp = local_stores_num[j];
							if(i != temp)
							{
								k.Set(temp);
							}
						}
					}
				}
				gen.Add(g);
				kill.Add(k);
			}

			/*
			for(i = 0;i < code_count;i++)
			{
				k = kill[i];
				Console.Write(i+": ");
				local_stores_num = k.GetNumberSet();
				for(j = 0;j < local_stores_num.Count;j++)
				{
					Console.Write(local_stores_num[j]+ " ");
				}
				Console.WriteLine();
			}
			*/
		}
	}
}
